package com.nickstumpos.android.easyVolume.playRinger.streams;

import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;

import com.nickstumpos.android.easyVolume.playRinger.IPlaySample;

public class AlarmPlaySample implements IPlaySample {

	private class Worker implements Runnable {

		private final Object	lock	= new Object();
		private Looper				looper;

		Worker(String name) {
			Thread t = new Thread(null, this, name);
			t.start();
			synchronized (this.lock) {
				while (this.looper == null) {
					try {
						this.lock.wait();
					} catch (InterruptedException ex) {
					}
				}
			}
		}

		public Looper getLooper() {
			return this.looper;
		}

		public void quit() {
			this.looper.quit();
		}

		public void run() {
			synchronized (this.lock) {
				Looper.prepare();
				this.looper = Looper.myLooper();
				this.lock.notifyAll();
			}
			Looper.loop();
		}
	}

	private static final int	PLAY_RING_ONCE		= 1;
	private static final int	STOP_RING					= 3;

	private static final int	PAUSE_LENGTH			= 1000;															

	// Uri for the ringtone.
	Uri												customRingtoneUri	= RingtoneManager
																									.getDefaultUri(RingtoneManager.TYPE_ALARM);
	Ringtone									alarmMedia;
	Context										context;
	private Worker						alarmThread;
	private Handler						alarmHandler;
	private boolean						alarmPending;
	private long							firstEventTime		= -1;

	private long							firstStartTime		= -1;

	public AlarmPlaySample(Context main) {
		this.context = main;

	}

	private boolean isPlaying() {
		synchronized (this) {
			return this.alarmMedia != null && this.alarmMedia.isPlaying()
					|| this.alarmHandler != null
					&& this.alarmHandler.hasMessages(AlarmPlaySample.PLAY_RING_ONCE);
		}
	}

	private void makeLooper() {
		if (this.alarmThread == null) {
			this.alarmThread = new Worker("alarm");
			this.alarmHandler = new Handler(this.alarmThread.getLooper()) {

				@Override
				public void handleMessage(Message msg) {
					Ringtone r = null;
					switch (msg.what) {
						case PLAY_RING_ONCE:
							if (AlarmPlaySample.this.alarmMedia == null
									&& !this.hasMessages(AlarmPlaySample.STOP_RING)) {
								r = RingtoneManager.getRingtone(AlarmPlaySample.this.context,
										AlarmPlaySample.this.customRingtoneUri);
								r.setStreamType(AudioManager.STREAM_ALARM);
								synchronized (AlarmPlaySample.this) {
									if (!this.hasMessages(AlarmPlaySample.STOP_RING)) {
										AlarmPlaySample.this.alarmMedia = r;
									}
								}
							}
							r = AlarmPlaySample.this.alarmMedia;
							while (r != null && !this.hasMessages(AlarmPlaySample.STOP_RING)) {
								if (!r.isPlaying()) {
									r.play();
								}
								synchronized (AlarmPlaySample.this) {
									AlarmPlaySample.this.alarmPending = false;
									if (AlarmPlaySample.this.firstStartTime < 0) {
										AlarmPlaySample.this.firstStartTime = SystemClock
												.elapsedRealtime();
									}
								}
								try {
									Thread.sleep(AlarmPlaySample.PAUSE_LENGTH);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
							break;
						case STOP_RING:
							r = (Ringtone) msg.obj;
							if (r != null) {
								r.stop();
							}
							this.getLooper().quit();
							break;
					}
				}
			};
		}
	}

	public void setCustomRingtoneUri(Uri uri) {
		if (uri != null) {
			this.customRingtoneUri = uri;
		}
	}

	@Override
	public void start() {

		synchronized (this) {

			if (!this.isPlaying() && !this.alarmPending) {
				this.makeLooper();
				this.alarmHandler.removeCallbacksAndMessages(null);
				this.alarmPending = true;
				if (this.firstEventTime < 0) {
					this.firstEventTime = SystemClock.elapsedRealtime();
					this.alarmHandler.sendEmptyMessage(AlarmPlaySample.PLAY_RING_ONCE);
				} else {
					if (this.firstStartTime > 0) {
						this.alarmHandler.sendEmptyMessageDelayed(
								AlarmPlaySample.PLAY_RING_ONCE, this.firstStartTime
										- this.firstEventTime);
					} else {
						this.firstEventTime = SystemClock.elapsedRealtime();
					}
				}
			}
		}

	}

	@Override
	public void stop() {
		synchronized (this) {
			if (this.alarmHandler != null) {
				this.alarmHandler.removeCallbacksAndMessages(null);
				Message msg = this.alarmHandler
						.obtainMessage(AlarmPlaySample.STOP_RING);
				msg.obj = this.alarmMedia;
				this.alarmHandler.sendMessage(msg);
				this.alarmThread = null;
				this.alarmHandler = null;
				this.alarmMedia = null;
				this.firstEventTime = -1;
				this.firstStartTime = -1;
				this.alarmPending = false;
			}
		}

	}

}
